<?php
/**
 * 文件上传类（本地）
 */

namespace app\common\lib;

class UploadFile
{
    private $dir = '';
    private $saveDir = '';
    const MAX_UPLOAD_SIZE = 10240; //单个文件最大尺寸 10M

    /**
     * 初始化
     * File constructor.
     * @param $appKey
     */
    function __construct()
    {
        $baseDir = public_path() . '/upload/';
        $this->dir = $baseDir . 'system';
        $this->saveDir = 'upload/system';
    }

    /**
     * 创建文件名称
     * User:端木凌风
     * Date:2023-11-08 09:05
     * @param $ext
     * @return object|array|void|mixed
     */
    public function createFileBaseName($ext)
    {
        return md5(microtime(true) . mt_rand(1, 1000)) . '.' . $ext;
    }


    private function initDir()
    {
        if (file_exists($this->dir)) {
            return true;
        }
        mkdir($this->dir);
        return true;
    }

    /**
     * 创建目录
     * User:端木凌风
     * Date:2023-11-08 09:14
     * @param array $path
     * @return object|array|void|mixed
     */
    private function createPath(array $path = [])
    {
        $dir = $this->dir;
        foreach ($path as $v) {
            if (!preg_match("/^[A-Za-z0-9_]+$/", $v)) {
                return funReturn(STATUS_CODE_DATAERROR, 'path只能由英文字母、数字、下划线组成');
            }
        }
        foreach ($path as $v) {
            $dir = $dir . '/' . $v;
            if (file_exists($dir)) {
                continue;
            }
            mkdir($dir);
        }
        return funReturn(STATUS_CODE_SUCCESS, 'success');
    }


    /**
     * 创建文件路径
     * User:端木凌风
     * Date:2023-11-08 09:28
     * @param $path
     * @return object|array|void|mixed
     */
    public function createSavePath($path)
    {

        $path = trim($path, '/');
        $pathArr = explode('/', $path);
        $res = $this->createPath($pathArr);
        if ($res['status'] != STATUS_CODE_SUCCESS) {
            return $res;
        }
        $returnData = ['localPath' => $this->dir . '/' . $path, 'savePath' => $this->saveDir . '/' . $path];
        return funReturn(STATUS_CODE_SUCCESS, 'success', $returnData);
    }

    /**
     * 检查参数
     * User:端木凌风
     * Date:2023-11-08 09:37
     * @param $param
     * @param $allowExt
     * @param $maxSize
     * @param $file
     * @return object|array|void|mixed
     */
    protected function checkData(array $param = [], array $allowExt = [], int $maxSize = 0, $file = null)

    {

        if (!isset($param['path'][0])) {
            return funReturn(STATUS_CODE_DATAERROR, '缺少path字段');
        }

        if ($file === null) {
            if (!isset($param['fileField'])) return funReturn(STATUS_CODE_DATAERROR, '缺少fileField字段');
            $file = request()->file($param['fileField']);
            if ($file === null) {
                return funReturn(STATUS_CODE_NOTFOUND, '上传文件不存在或超过服务器限制');
            }
        }
        if (!$file->isValid()) {
            return funReturn(STATUS_CODE_DATAERROR, '无效文件');
        }
        $ext = $file->extension();     // 扩展名
        $ext = strtolower($ext);
        if ($allowExt and !in_array($ext, $allowExt)) {
            return funReturn(STATUS_CODE_DATAERROR, '只允许上传' . implode(',', $allowExt) . '类型文件');
        }
        $size = $file->getSize();
        $limitMaxSize = $maxSize > 0 ? $maxSize : self::MAX_UPLOAD_SIZE;
        if ($size / 1024 > $limitMaxSize) {
            return funReturn(STATUS_CODE_DATAERROR, '文件不能超过' . $limitMaxSize . 'Kb');
        }
        $param['path'] = trim($param['path'], '/');
        $pathArr = explode('/', $param['path']);
        return funReturn(STATUS_CODE_SUCCESS, '', ['fileObj' => $file, 'pathArr' => $pathArr, 'path' => $param['path'], 'originalName' => $file->getOriginalName()]);


    }

    /**
     * 上传
     * User:端木凌风
     * Date:2023-11-08 09:05
     * @param array $param
     * @param array $allowExt
     * @param int $maxSize
     * @param $file
     * @return object|array|void|mixed
     */
    public function upload(array $param = [], array $allowExt = [], int $maxSize = 0, $file = null)
    {
        if (!$this->initDir()) {
            return funReturn(STATUS_CODE_DATAERROR, '上传失败');
        }

        $checkRes = $this->checkData($param, $allowExt, $maxSize, $file);
        if ($checkRes['status'] != STATUS_CODE_SUCCESS) {
            return $checkRes;
        }
        $file = $checkRes['data']['fileObj'];
        if ($file === null) {
            return funReturn(STATUS_CODE_NOTFOUND, '上传文件不存在或超过服务器限制');
        }
        $pathRes = $this->createSavePath($checkRes['data']['path']);
        if ($pathRes['status'] != STATUS_CODE_SUCCESS) {
            return funReturn(STATUS_CODE_NOTFOUND, '路径错误');
        }
        $ext = strtolower($file->extension()); //获取文件后缀名
        $filename = md5(microtime(true) . uniqid()) . '.' . $ext;
        $savePath = $pathRes['data']['savePath'] . '/' . $filename;
        if ($file->move($pathRes['data']['localPath'], $filename)) {
            return funReturn(STATUS_CODE_SUCCESS, '上传成功', [
                'fileName' => $filename,
                'ext' => $ext,
                'url' => $this->turnSavePathToUrl($savePath),
                'savePath' => $savePath
            ]);
        } else {
            return funReturn(STATUS_CODE_NOTFOUND, '上传失败');
        }
    }

    /**
     * 把存储路径转化为url地址
     * User:端木凌风
     * Date:2023-11-08 09:17
     * @param $savePath
     * @return object|array|void|mixed
     */
    public static function turnSavePathToUrl($savePath)
    {
        /*$savePath = trim($savePath, '/');
        $domain = config('app.app_host');
        $domain = trim($domain, '/');
        return $savePath ? $domain . '/' . $savePath : '';*/
        return File::turnSavePathToUrl($savePath);
    }
}